/* add user code begin Header */
/**
**************************************************************************
* @file     at32f415_wk_config.c
* @brief    work bench config program
**************************************************************************
*                       Copyright notice & Disclaimer
*
* The software Board Support Package (BSP) that is made available to
* download from Artery official website is the copyrighted work of Artery.
* Artery authorizes customers to use, copy, and distribute the BSP
* software and its related documentation for the purpose of design and
* development in conjunction with Artery microcontrollers. Use of the
* software is governed by this copyright notice and the following disclaimer.
*
* THIS SOFTWARE IS PROVIDED ON "AS IS" BASIS WITHOUT WARRANTIES,
* GUARANTEES OR REPRESENTATIONS OF ANY KIND. ARTERY EXPRESSLY DISCLAIMS,
* TO THE FULLEST EXTENT PERMITTED BY LAW, ALL EXPRESS, IMPLIED OR
* STATUTORY OR OTHER WARRANTIES, GUARANTEES OR REPRESENTATIONS,
* INCLUDING BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, OR NON-INFRINGEMENT.
*
**************************************************************************
*/
/* add user code end Header */

#include "at32f415_wk_config.h"


//串口收发缓冲区定义
uint8_t usart_tx_buff[USART_TX_BUFF_SIZE];
uint8_t usart_rx_buff[USART_RX_BUFF_SIZE];


//按键状态标志位  0:无效   1：按键有效
__IO uint8_t		BUTTON_SINGLE_Click_Flag = 0;
__IO uint8_t		BUTTON_DOUBLE_Click_Flag = 0;
__IO uint8_t		BUTTON_SHORT_PRESS_Flag = 0;
__IO uint8_t		BUTTON_LONG_PRESS_Flag = 0;

__IO uint8_t		K1_SINGLE_Click_Flag = 0;
__IO uint8_t		K1_DOUBLE_Click_Flag = 0;
__IO uint8_t		K1_SHORT_PRESS_Flag = 0;
__IO uint8_t		K1_LONG_PRESS_Flag = 0;

__IO uint8_t		K2_SINGLE_Click_Flag = 0;
__IO uint8_t		K2_DOUBLE_Click_Flag = 0;
__IO uint8_t		K2_SHORT_PRESS_Flag = 0;
__IO uint8_t		K2_LONG_PRESS_Flag = 0;


//定义一组按钮结构体变量
static flex_button_t user_button[FLEX_BUTTON_MAX];


#if defined ( __GNUC__ ) && !defined (__clang__)
/* with gcc/raisonance, small printf (option ld linker->libraries->small printf set to 'yes') calls

__io_putchar() */
#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
#else
#define PUTCHAR_PROTOTYPE int fputc(int ch, FILE *f)
#endif /* __gnuc__ */

/**
* @brief  retargets the c library printf function to the usart.
* @param  none
* @retval none
*/
PUTCHAR_PROTOTYPE
{
    while(usart_flag_get(USART1, USART_TDBE_FLAG) == RESET);
    usart_data_transmit(USART1, ch);
    return ch;
}

/**
* @brief  system clock config program
* @note   the system clock is configured as follow:
*         system clock (sclk)   = hick / 12 * pll_mult
*         system clock source   = HICK_VALUE
*         - sclk                = 144000000
*         - ahbdiv              = 1
*         - ahbclk              = 144000000
*         - apb1div             = 2
*         - apb1clk             = 72000000
*         - apb2div             = 2
*         - apb2clk             = 72000000
*         - pll_mult            = 36
*         - flash_wtcyc         = 4 cycle
* @param  none
* @retval none
*/
void wk_system_clock_config(void)
{
    /* reset crm */
    crm_reset();

    /* config flash psr register */
    flash_psr_set(FLASH_WAIT_CYCLE_4);

    /* enable hick */
    crm_clock_source_enable(CRM_CLOCK_SOURCE_HEXT, TRUE);

    /* wait till hext is ready */
    while(crm_hext_stable_wait() == ERROR)
    {
    }

    /* config pll clock resource */
    crm_pll_config(CRM_PLL_SOURCE_HEXT_DIV, CRM_PLL_MULT_36);

    /* enable pll */
    crm_clock_source_enable(CRM_CLOCK_SOURCE_PLL, TRUE);

    /* wait till pll is ready */
    while(crm_flag_get(CRM_PLL_STABLE_FLAG) != SET)
    {
    }

    /* config ahbclk */
    crm_ahb_div_set(CRM_AHB_DIV_1);

    /* config apb2clk, the maximum frequency of APB2 clock is 75 MHz  */
    crm_apb2_div_set(CRM_APB2_DIV_2);

    /* config apb1clk, the maximum frequency of APB1 clock is 75 MHz  */
    crm_apb1_div_set(CRM_APB1_DIV_2);

    /* enable auto step mode */
    crm_auto_step_mode_enable(TRUE);

    /* select pll as system clock source */
    crm_sysclk_switch(CRM_SCLK_PLL);

    /* wait till pll is used as system clock source */
    while(crm_sysclk_switch_status_get() != CRM_SCLK_PLL)
    {
    }

    /* disable auto step mode */
    crm_auto_step_mode_enable(FALSE);

    /* update system_core_clock global variable */
    system_core_clock_update();
}

/**
* @brief  config periph clock
* @param  none
* @retval none
*/
void wk_periph_clock_config(void)
{
    crm_periph_clock_enable(CRM_DMA1_PERIPH_CLOCK, TRUE);
    crm_periph_clock_enable(CRM_IOMUX_PERIPH_CLOCK, TRUE);
    crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);
    crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);
    crm_periph_clock_enable(CRM_GPIOC_PERIPH_CLOCK, TRUE);
    crm_periph_clock_enable(CRM_GPIOD_PERIPH_CLOCK, TRUE);
    crm_periph_clock_enable(CRM_GPIOF_PERIPH_CLOCK, TRUE);
    crm_periph_clock_enable(CRM_ADC1_PERIPH_CLOCK, TRUE);
    crm_periph_clock_enable(CRM_USART1_PERIPH_CLOCK, TRUE);
    crm_periph_clock_enable(CRM_TMR9_PERIPH_CLOCK, TRUE);
    crm_periph_clock_enable(CRM_TMR10_PERIPH_CLOCK, TRUE);
    crm_periph_clock_enable(CRM_TMR11_PERIPH_CLOCK, TRUE);
    crm_periph_clock_enable(CRM_I2C1_PERIPH_CLOCK, TRUE);
    crm_periph_clock_enable(CRM_I2C2_PERIPH_CLOCK, TRUE);
}

/**
* @brief  init debug function.
* @param  none
* @retval none
*/
void wk_debug_config(void)
{
    /* jtag-dp disabled and sw-dp enabled */
    gpio_pin_remap_config(SWJTAG_GMUX_010, TRUE);
}

/**
* @brief  nvic config
* @param  none
* @retval none
*/
void wk_nvic_config(void)
{
    nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);

    NVIC_SetPriority(MemoryManagement_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 0));
    NVIC_SetPriority(BusFault_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 0));
    NVIC_SetPriority(UsageFault_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 0));
    NVIC_SetPriority(SVCall_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 0));
    NVIC_SetPriority(DebugMonitor_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 0));
    NVIC_SetPriority(PendSV_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 0, 0));
    NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(), 15, 0));
    nvic_irq_enable(DMA1_Channel1_IRQn, 0, 0);
    nvic_irq_enable(DMA1_Channel2_IRQn, 0, 0);
    nvic_irq_enable(TMR1_BRK_TMR9_IRQn, 2, 0);
}

/**
* @brief  init gpio_input/gpio_output/gpio_analog/eventout function.
* @param  none
* @retval none
*/
void wk_gpio_config(void)
{
    gpio_init_type gpio_init_struct;
    gpio_default_para_init(&gpio_init_struct);

    /* gpio input config */
    gpio_init_struct.gpio_mode = GPIO_MODE_INPUT;
    gpio_init_struct.gpio_pins = K2_PIN | BUTTON_PIN | K1_PIN;
    gpio_init_struct.gpio_pull = GPIO_PULL_DOWN;
    gpio_init(GPIOB, &gpio_init_struct);

    /* gpio output config */
    gpio_bits_reset(LED_GPIO_PORT, LED_PIN);

    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;
    gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
    gpio_init_struct.gpio_mode = GPIO_MODE_OUTPUT;
    gpio_init_struct.gpio_pins = LED_PIN;
    gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
    gpio_init(LED_GPIO_PORT, &gpio_init_struct);
    
    gpio_init_struct.gpio_pins = ADSET_PIN;
    gpio_init(ADSET_GPIO_PORT, &gpio_init_struct);

    /* gpio analog config */
    gpio_init_struct.gpio_mode = GPIO_MODE_ANALOG;
    gpio_init_struct.gpio_pins = GPIO_PINS_13 | GPIO_PINS_14 | GPIO_PINS_15;
    gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
    gpio_init(GPIOC, &gpio_init_struct);

    gpio_init_struct.gpio_mode = GPIO_MODE_ANALOG;
    gpio_init_struct.gpio_pins = GPIO_PINS_0 | GPIO_PINS_1;
    gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
    gpio_init(GPIOD, &gpio_init_struct);

    gpio_init_struct.gpio_mode = GPIO_MODE_ANALOG;
    gpio_init_struct.gpio_pins = GPIO_PINS_0 | GPIO_PINS_1 | GPIO_PINS_4 | GPIO_PINS_5 | GPIO_PINS_7 |
                                 GPIO_PINS_8 | GPIO_PINS_11 | GPIO_PINS_12 | GPIO_PINS_15;
    gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
    gpio_init(GPIOA, &gpio_init_struct);

    gpio_init_struct.gpio_mode = GPIO_MODE_ANALOG;
    gpio_init_struct.gpio_pins = GPIO_PINS_0 | GPIO_PINS_1 | GPIO_PINS_12 | GPIO_PINS_13 |
                                 GPIO_PINS_14 | GPIO_PINS_15 | GPIO_PINS_8;
    gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
    gpio_init(GPIOB, &gpio_init_struct);

    gpio_init_struct.gpio_mode = GPIO_MODE_ANALOG;
    gpio_init_struct.gpio_pins = GPIO_PINS_6 | GPIO_PINS_7;
    gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
    gpio_init(GPIOF, &gpio_init_struct);
    
    ADR_SET_HIGH();             //内置传感器地址选择高电平
}

/**
* @brief  init i2c1 function.
* @param  none
* @retval none
*/
void wk_i2c1_init(void)
{
    gpio_init_type gpio_init_struct;

    gpio_default_para_init(&gpio_init_struct);

    /* configure the SCL pin */
    gpio_init_struct.gpio_out_type = GPIO_OUTPUT_OPEN_DRAIN;
    gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
    gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;
    gpio_init_struct.gpio_pins = GPIO_PINS_6;
    gpio_init(GPIOB, &gpio_init_struct);

    /* configure the SDA pin */
    gpio_init_struct.gpio_out_type = GPIO_OUTPUT_OPEN_DRAIN;
    gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
    gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;
    gpio_init_struct.gpio_pins = GPIO_PINS_7;
    gpio_init(GPIOB, &gpio_init_struct);

    i2c_init(I2C1, I2C_FSMODE_DUTY_2_1, 400000);
    i2c_own_address1_set(I2C1, I2C_ADDRESS_MODE_7BIT, 0x0);
    i2c_ack_enable(I2C1, TRUE);
    i2c_clock_stretch_enable(I2C1, TRUE);
    i2c_general_call_enable(I2C1, FALSE);

    i2c_enable(I2C1, TRUE);
}

/**
* @brief  init i2c2 function.
* @param  none
* @retval none
*/
void wk_i2c2_init(void)
{
    gpio_init_type gpio_init_struct;

    gpio_default_para_init(&gpio_init_struct);

    /* configure the SCL pin */
    gpio_init_struct.gpio_out_type = GPIO_OUTPUT_OPEN_DRAIN;
    gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
    gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;
    gpio_init_struct.gpio_pins = GPIO_PINS_10;
    gpio_init(GPIOB, &gpio_init_struct);

    /* configure the SDA pin */
    gpio_init_struct.gpio_out_type = GPIO_OUTPUT_OPEN_DRAIN;
    gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
    gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;
    gpio_init_struct.gpio_pins = GPIO_PINS_11;
    gpio_init(GPIOB, &gpio_init_struct);

    i2c_init(I2C2, I2C_FSMODE_DUTY_2_1, 400000);
    i2c_own_address1_set(I2C2, I2C_ADDRESS_MODE_7BIT, 0x0);
    i2c_ack_enable(I2C2, TRUE);
    i2c_clock_stretch_enable(I2C2, TRUE);
    i2c_general_call_enable(I2C2, FALSE);

    i2c_enable(I2C2, TRUE);
}

/**
* @brief  initializes peripherals used by the i2c.
* @param  none
* @retval none
*/
void i2c_lowlevel_init(i2c_handle_type* hi2c)
{
    gpio_init_type gpio_initstructure;

    if(hi2c->i2cx == I2C1)
    {
        /* i2c periph clock enable */
//相关时钟已另处开启，这里注释掉
        crm_periph_clock_enable(CRM_I2C1_PERIPH_CLOCK, TRUE);
        crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);


        /* gpio configuration */
        gpio_initstructure.gpio_out_type       = GPIO_OUTPUT_OPEN_DRAIN;
        gpio_initstructure.gpio_pull           = GPIO_PULL_NONE;
        gpio_initstructure.gpio_mode           = GPIO_MODE_MUX;
        gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;

        /* configure i2c pins: scl */
        gpio_initstructure.gpio_pins = GPIO_PINS_6;
        gpio_init(GPIOB, &gpio_initstructure);

        /* configure i2c pins: sda */
        gpio_initstructure.gpio_pins = GPIO_PINS_7;
        gpio_init(GPIOB, &gpio_initstructure);

        /* configure and enable i2c dma channel interrupt */
//不使用相关DMA中断 这里注释掉
//        dma_interrupt_enable(DMA2_CHANNEL1, DMA_FDT_INT, TRUE);
//        nvic_irq_enable(DMA2_Channel1_IRQn, 0, 0);
//    nvic_irq_enable(I2Cx_DMA_RX_IRQn, 0, 0);

        /* configure and enable i2c interrupt */
//不使用相关I2C中断 这里注释掉
//        nvic_irq_enable(I2C1_EVT_IRQn, 0, 0);
//        nvic_irq_enable(I2C1_ERR_IRQn, 0, 0);

        /* i2c dma tx and rx channels configuration */
        /* enable the dma clock */
//        crm_periph_clock_enable(CRM_DMA2_PERIPH_CLOCK, TRUE);

        /* i2c dma channel configuration */
//不使用相关DMA 这里注释掉
//        hi2c->dma_tx_channel = DMA2_CHANNEL1;
//        hi2c->dma_rx_channel = DMA2_CHANNEL2;

//        dma_reset(hi2c->dma_tx_channel);
//        dma_reset(hi2c->dma_rx_channel);

//        dma_default_para_init(&hi2c->dma_init_struct);
//        hi2c->dma_init_struct.peripheral_inc_enable    = FALSE;
//        hi2c->dma_init_struct.memory_inc_enable        = TRUE;
//        hi2c->dma_init_struct.peripheral_data_width    = DMA_PERIPHERAL_DATA_WIDTH_BYTE;
//        hi2c->dma_init_struct.memory_data_width        = DMA_MEMORY_DATA_WIDTH_BYTE;
//        hi2c->dma_init_struct.loop_mode_enable         = FALSE;
//        hi2c->dma_init_struct.priority                 = DMA_PRIORITY_LOW;
//        hi2c->dma_init_struct.direction                = DMA_DIR_MEMORY_TO_PERIPHERAL;

//        dma_init(hi2c->dma_tx_channel, &hi2c->dma_init_struct);
//        dma_init(hi2c->dma_rx_channel, &hi2c->dma_init_struct);

//        dma_flexible_config(DMA2, FLEX_CHANNEL1, DMA_FLEXIBLE_I2C1_TX);
//        dma_channel_enable(DMA2_CHANNEL1, TRUE); /* i2c1 tx begin dma  */

        i2c_init(I2C1, I2C_FSMODE_DUTY_2_1, 400000);                //设置I2C通信速率
        i2c_own_address1_set(I2C1, I2C_ADDRESS_MODE_7BIT, 0x0);
//        i2c_ack_enable(I2C1, TRUE);
//        i2c_clock_stretch_enable(I2C1, TRUE);
//        i2c_general_call_enable(I2C1, FALSE);

    } else if(hi2c->i2cx == I2C2) {
        /* i2c periph clock enable */
//相关时钟已另处开启，这里注释掉
        crm_periph_clock_enable(CRM_I2C2_PERIPH_CLOCK, TRUE);
        crm_periph_clock_enable(CRM_GPIOB_PERIPH_CLOCK, TRUE);

        /* gpio configuration */
        gpio_initstructure.gpio_out_type       = GPIO_OUTPUT_OPEN_DRAIN;
        gpio_initstructure.gpio_pull           = GPIO_PULL_NONE;
        gpio_initstructure.gpio_mode           = GPIO_MODE_MUX;
        gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;

        /* configure i2c pins: scl */
        gpio_initstructure.gpio_pins = GPIO_PINS_10;
        gpio_init(GPIOB, &gpio_initstructure);

        /* configure i2c pins: sda */
        gpio_initstructure.gpio_pins = GPIO_PINS_11;
        gpio_init(GPIOB, &gpio_initstructure);

        /* configure and enable i2c dma channel interrupt */
//不使用相关DMA中断 这里注释掉
//    nvic_irq_enable(I2Cx_DMA_TX_IRQn, 0, 0);
//    nvic_irq_enable(I2Cx_DMA_RX_IRQn, 0, 0);

        /* configure and enable i2c interrupt */
//不使用相关DMA中断 这里注释掉
//    nvic_irq_enable(I2Cx_EVT_IRQn, 0, 0);
//    nvic_irq_enable(I2Cx_ERR_IRQn, 0, 0);

        /* i2c dma tx and rx channels configuration */
        /* enable the dma clock */
//不使用相关DMA 这里注释掉
//    crm_periph_clock_enable(I2Cx_DMA_CLK, TRUE);

        /* i2c dma channel configuration */
//不使用相关DMA 这里注释掉
//    hi2c->dma_tx_channel = I2Cx_DMA_TX_CHANNEL;
//    hi2c->dma_rx_channel = I2Cx_DMA_RX_CHANNEL;

//    dma_reset(hi2c->dma_tx_channel);
//    dma_reset(hi2c->dma_rx_channel);

//    dma_default_para_init(&hi2c->dma_init_struct);
//    hi2c->dma_init_struct.peripheral_inc_enable    = FALSE;
//    hi2c->dma_init_struct.memory_inc_enable        = TRUE;
//    hi2c->dma_init_struct.peripheral_data_width    = DMA_PERIPHERAL_DATA_WIDTH_BYTE;
//    hi2c->dma_init_struct.memory_data_width        = DMA_MEMORY_DATA_WIDTH_BYTE;
//    hi2c->dma_init_struct.loop_mode_enable         = FALSE;
//    hi2c->dma_init_struct.priority                 = DMA_PRIORITY_LOW;
//    hi2c->dma_init_struct.direction                = DMA_DIR_MEMORY_TO_PERIPHERAL;

//    dma_init(hi2c->dma_tx_channel, &hi2c->dma_init_struct);
//    dma_init(hi2c->dma_rx_channel, &hi2c->dma_init_struct);

        i2c_init(I2C2, I2C_FSMODE_DUTY_2_1, 400000);                //设置I2C通信速率
        i2c_own_address1_set(I2C2, I2C_ADDRESS_MODE_7BIT, 0x0);
//        i2c_ack_enable(I2C2, TRUE);
//        i2c_clock_stretch_enable(I2C2, TRUE);
//        i2c_general_call_enable(I2C2, FALSE);

    }
}

/**
* @brief  init usart1 function
* @param  none
* @retval none
*/
void wk_usart1_init(void)
{
    gpio_init_type gpio_init_struct;
    gpio_default_para_init(&gpio_init_struct);

    /* configure the TX pin */
    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;
    gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
    gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
    gpio_init_struct.gpio_pins = GPIO_PINS_9;
    gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
    gpio_init(GPIOA, &gpio_init_struct);

    /* configure the RX pin */
    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;
    gpio_init_struct.gpio_out_type  = GPIO_OUTPUT_PUSH_PULL;
    gpio_init_struct.gpio_mode = GPIO_MODE_INPUT;
    gpio_init_struct.gpio_pins = GPIO_PINS_10;
    gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
    gpio_init(GPIOA, &gpio_init_struct);

    /* configure param */
    usart_init(USART1, 115200, USART_DATA_8BITS, USART_STOP_1_BIT);
    usart_transmitter_enable(USART1, TRUE);
    usart_receiver_enable(USART1, TRUE);
    usart_parity_selection_config(USART1, USART_PARITY_NONE);

//    usart_dma_transmitter_enable(USART1, TRUE);
//    usart_dma_receiver_enable(USART1, TRUE);

    usart_hardware_flow_control_set(USART1, USART_HARDWARE_FLOW_NONE);

    usart_enable(USART1, TRUE);
}

/**
* @brief  init tmr9 function.
* @param  none
* @retval none
*/
void wk_tmr9_init(void)
{
    /* configure counter settings */
    tmr_base_init(TMR9, 999, 143);
    tmr_cnt_dir_set(TMR9, TMR_COUNT_UP);
    tmr_clock_source_div_set(TMR9, TMR_CLOCK_DIV1);
    tmr_period_buffer_enable(TMR9, FALSE);

    tmr_counter_enable(TMR9, TRUE);
    /**
    * Users need to configure TMR9 interrupt functions according to the actual application.
    * 1. Call the below function to enable the corresponding TMR9 interrupt.
    *     --tmr_interrupt_enable(...)
    * 2. Add the user's interrupt handler code into the below function in the at32f415_int.c file.
    *     --void TMR1_BRK_TMR9_IRQHandler(void)
    */

    tmr_interrupt_enable(TMR9, TMR_OVF_INT, TRUE);
}

/**
* @brief  init tmr10 function.
* @param  none
* @retval none
*/
void wk_tmr10_init(void)
{
    gpio_init_type gpio_init_struct;
    tmr_output_config_type tmr_output_struct;
    gpio_default_para_init(&gpio_init_struct);

    /* configure the CH1 pin */
    gpio_init_struct.gpio_pins = PWM_PIN;
    gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
    gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
    gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;
    gpio_init(PWM_GPIO_PORT, &gpio_init_struct);

    /* GPIO PIN remap */
    gpio_pin_remap_config(TMR10_GMUX, TRUE);

    /* configure counter settings */
    tmr_base_init(TMR10, 9999, 14399);
    tmr_cnt_dir_set(TMR10, TMR_COUNT_UP);
    tmr_clock_source_div_set(TMR10, TMR_CLOCK_DIV1);
    tmr_period_buffer_enable(TMR10, FALSE);

    /* configure channel 1 output settings */
    tmr_output_struct.oc_mode = TMR_OUTPUT_CONTROL_PWM_MODE_A;
    tmr_output_struct.oc_output_state = TRUE;
    tmr_output_struct.occ_output_state = FALSE;
    tmr_output_struct.oc_polarity = TMR_OUTPUT_ACTIVE_HIGH;         //有效电平为高
    tmr_output_struct.occ_polarity = TMR_OUTPUT_ACTIVE_HIGH;        //有效电平为高
    tmr_output_struct.oc_idle_state = FALSE;
    tmr_output_struct.occ_idle_state = FALSE;
    tmr_output_channel_config(TMR10, TMR_SELECT_CHANNEL_1, &tmr_output_struct);
    tmr_channel_value_set(TMR10, TMR_SELECT_CHANNEL_1, 0);
    tmr_output_channel_buffer_enable(TMR10, TMR_SELECT_CHANNEL_1, FALSE);

    tmr_output_channel_immediately_set(TMR10, TMR_SELECT_CHANNEL_1, FALSE);

    tmr_counter_enable(TMR10, TRUE);
}

/**
* @brief  init tmr11 function.
* @param  none
* @retval none
*/
void wk_tmr11_init(void)
{
    gpio_init_type gpio_init_struct;
    tmr_output_config_type tmr_output_struct;
    gpio_default_para_init(&gpio_init_struct);

    /* configure the CH1 pin */
    gpio_init_struct.gpio_pins = TONE_PIN;
    gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
    gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
    gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
    gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;
    gpio_init(TONE_GPIO_PORT, &gpio_init_struct);

    /* configure counter settings */
    tmr_base_init(TMR11, 1499, 143);
    tmr_cnt_dir_set(TMR11, TMR_COUNT_UP);
    tmr_clock_source_div_set(TMR11, TMR_CLOCK_DIV1);
    tmr_period_buffer_enable(TMR11, FALSE);

    /* configure channel 1 output settings */
    tmr_output_struct.oc_mode = TMR_OUTPUT_CONTROL_PWM_MODE_A;
    tmr_output_struct.oc_output_state = TRUE;
    tmr_output_struct.occ_output_state = FALSE;
    tmr_output_struct.oc_polarity = TMR_OUTPUT_ACTIVE_HIGH;         //有效电平为高
    tmr_output_struct.occ_polarity = TMR_OUTPUT_ACTIVE_HIGH;        //有效电平为高
    tmr_output_struct.oc_idle_state = FALSE;
    tmr_output_struct.occ_idle_state = FALSE;
    tmr_output_channel_config(TMR11, TMR_SELECT_CHANNEL_1, &tmr_output_struct);
    tmr_channel_value_set(TMR11, TMR_SELECT_CHANNEL_1, 0);
    tmr_output_channel_buffer_enable(TMR11, TMR_SELECT_CHANNEL_1, FALSE);

    tmr_output_channel_immediately_set(TMR11, TMR_SELECT_CHANNEL_1, FALSE);

//初始化后，注释掉使能操作，默认定时器停止
//    tmr_counter_enable(TMR11, TRUE);
}

/**
* @brief  init wdt function.
* @param  none
* @retval none
*/
void wk_wdt_init(void)
{
    wdt_register_write_enable(TRUE);
    wdt_divider_set(WDT_CLK_DIV_16);
    wdt_reload_value_set(0xEA5);        //咬人周期1500ms
    wdt_counter_reload();               //出生先喂一口

    /* if enabled, please feed the dog through wdt_counter_reload() function */
//初始化后，注释掉使能操作，默认看门狗停止
//wdt_enable();
}

/**
* @brief  init adc1 function.
* @param  none
* @retval none
*/
void wk_adc1_init(void)
{
    gpio_init_type gpio_init_struct;
    adc_base_config_type adc_base_struct;

    gpio_default_para_init(&gpio_init_struct);

    /*gpio--------------------------------------------------------------------*/
    /* configure the IN3 pin */
    gpio_init_struct.gpio_mode = GPIO_MODE_ANALOG;
    gpio_init_struct.gpio_pins = ADC_PIN;
    gpio_init(ADC_GPIO_PORT, &gpio_init_struct);

    crm_adc_clock_div_set(CRM_ADC_DIV_4);

    /*adc_settings--------------------------------------------------------------------*/
    adc_base_default_para_init(&adc_base_struct);
    adc_base_struct.sequence_mode = FALSE;
    adc_base_struct.repeat_mode = FALSE;
    adc_base_struct.data_align = ADC_RIGHT_ALIGNMENT;
    adc_base_struct.ordinary_channel_length = 1;
    adc_base_config(ADC1, &adc_base_struct);

    /* adc_ordinary_conversionmode-------------------------------------------- */
    adc_ordinary_channel_set(ADC1, ADC_CHANNEL_3, 1, ADC_SAMPLETIME_239_5);
    adc_ordinary_conversion_trigger_set(ADC1, ADC12_ORDINARY_TRIG_SOFTWARE, TRUE);
    adc_ordinary_part_mode_enable(ADC1, FALSE);

    adc_enable(ADC1, TRUE);

    /* adc calibration-------------------------------------------------------- */
    adc_calibration_init(ADC1);
    while(adc_calibration_init_status_get(ADC1));
    adc_calibration_start(ADC1);
    while(adc_calibration_status_get(ADC1));
}


/**
* @brief  init dma1 channel1 for "usart1_tx"
* @param  none
* @retval none
*/
void wk_dma1_channel1_init(void)
{
    dma_init_type dma_init_struct;

    dma_reset(DMA1_CHANNEL1);
    dma_default_para_init(&dma_init_struct);
    dma_init_struct.direction = DMA_DIR_MEMORY_TO_PERIPHERAL;
    dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_BYTE;
    dma_init_struct.memory_inc_enable = TRUE;
    dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_BYTE;
    dma_init_struct.peripheral_inc_enable = FALSE;
    dma_init_struct.priority = DMA_PRIORITY_LOW;
    dma_init_struct.loop_mode_enable = FALSE;
    dma_init(DMA1_CHANNEL1, &dma_init_struct);

    /* flexible function enable */
    dma_flexible_config(DMA1, FLEX_CHANNEL1, DMA_FLEXIBLE_UART1_TX);
    /**
    * Users need to configure DMA1 interrupt functions according to the actual application.
    * 1. Call the below function to enable the corresponding DMA1 interrupt.
    *     --dma_interrupt_enable(...)
    * 2. Add the user's interrupt handler code into the below function in the at32f415_int.c file.
    *     --void DMA1_Channel1_IRQHandler(void)
    */
}

/**
* @brief  init dma1 channel2 for "usart1_rx"
* @param  none
* @retval none
*/
void wk_dma1_channel2_init(void)
{
    dma_init_type dma_init_struct;

    dma_reset(DMA1_CHANNEL2);
    dma_default_para_init(&dma_init_struct);
    dma_init_struct.direction = DMA_DIR_PERIPHERAL_TO_MEMORY;
    dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_BYTE;
    dma_init_struct.memory_inc_enable = TRUE;
    dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_BYTE;
    dma_init_struct.peripheral_inc_enable = FALSE;
    dma_init_struct.priority = DMA_PRIORITY_LOW;
    dma_init_struct.loop_mode_enable = FALSE;
    dma_init(DMA1_CHANNEL2, &dma_init_struct);

    /* flexible function enable */
    dma_flexible_config(DMA1, FLEX_CHANNEL2, DMA_FLEXIBLE_UART1_RX);
    /**
    * Users need to configure DMA1 interrupt functions according to the actual application.
    * 1. Call the below function to enable the corresponding DMA1 interrupt.
    *     --dma_interrupt_enable(...)
    * 2. Add the user's interrupt handler code into the below function in the at32f415_int.c file.
    *     --void DMA1_Channel2_IRQHandler(void)
    */
}

/**
* @brief  config dma channel transfer parameter
* @param  dmax_channely: DMAx_CHANNELy
* @param  peripheral_base_addr: peripheral address.
* @param  memory_base_addr: memory address.
* @param  buffer_size: buffer size.
* @retval none
*/
void wk_dma_channel_config(dma_channel_type* dmax_channely, uint32_t peripheral_base_addr, uint32_t memory_base_addr, uint16_t buffer_size)
{
    dmax_channely->dtcnt = buffer_size;
    dmax_channely->paddr = peripheral_base_addr;
    dmax_channely->maddr = memory_base_addr;
}


/**
  * @brief   ERTC配置函数 
  * @param   none
  * @retval  none
  */
void ertc_config(void)
{
  /* enable the pwc clock interface */
  crm_periph_clock_enable(CRM_PWC_PERIPH_CLOCK, TRUE);

  /* allow access to ertc */
  pwc_battery_powered_domain_access(TRUE);

  /* reset ertc domain */
  crm_battery_powered_domain_reset(TRUE);
  crm_battery_powered_domain_reset(FALSE);

  /* enable the lext osc */
  crm_clock_source_enable(CRM_CLOCK_SOURCE_LICK, TRUE);

  /* wait till lext is ready */
//  while(crm_flag_get(CRM_LEXT_STABLE_FLAG) == RESET)
//  {
//  }

  /* select the ertc clock source */
  crm_ertc_clock_select(CRM_ERTC_CLOCK_LICK);

  /* enable the ertc clock */
  crm_ertc_clock_enable(TRUE);

  /* deinitializes the ertc registers */
  ertc_reset();

  /* wait for ertc apb registers update */
  ertc_wait_update();

  /* configure the ertc divider */
  /* ertc second(1hz) = ertc_clk / (div_a + 1) * (div_b + 1) */
  ertc_divider_set(127, 25);        //100ms

  /* configure the ertc hour mode */
  ertc_hour_mode_set(ERTC_HOUR_MODE_24);

  /* set date: 2021-05-01 */
  ertc_date_set(21, 5, 1, 5);

  /* set time: 12:00:00 */
  ertc_time_set(12, 0, 0, ERTC_AM);
}

/**
  * @brief   定时器唤醒配置函数 
  * @param   none
  * @retval  none
  */
void wakeup_timer_config(void)
{
  exint_init_type exint_init_struct;

  /* select the wakeup timer clock source */
  ertc_wakeup_clock_set(ERTC_WAT_CLK_CK_B_16BITS);

  /* set wakeup time: 1s  根据ertc配置*/
  ertc_wakeup_counter_set(10 - 1);

  /* enable ertc wakeup timer interrupt */
  ertc_interrupt_enable(ERTC_WAT_INT, TRUE);

  /* enable the wakeup timer */
  ertc_wakeup_enable(TRUE);

  /* ertc wakeup timer interrupt configuration */
  /* exint configuration */
  exint_default_para_init(&exint_init_struct);
  exint_init_struct.line_enable   = TRUE;
  exint_init_struct.line_mode     = EXINT_LINE_INTERRUPT;
  exint_init_struct.line_select   = EXINT_LINE_22;
  exint_init_struct.line_polarity = EXINT_TRIGGER_RISING_EDGE;
  exint_init(&exint_init_struct);

  /* enable the ertc interrupt */
  nvic_irq_enable(ERTC_WKUP_IRQn, 0, 1);
}

/**
  * @brief   进入待机低功耗模式 
  * @param   none
  * @retval  none
  */
void enter_standby_mode(void)
{
	/* ertc configuration */
	ertc_config();

	/* ertc wakeup timer configuration */
	wakeup_timer_config();

	/* enter standby mode */
	pwc_standby_mode_enter();
}


/**
* @brief    读取按键电平
* @param    按键结构体指针
* @retval   返回按键的当前电平
*/
static uint8_t common_btn_read(void *arg)
{
    uint8_t value = 0;

    flex_button_t *btn = (flex_button_t *)arg;

    switch (btn->id) {
    case button:
        value = gpio_input_data_bit_read(BUTTON_GPIO_PORT, BUTTON_PIN);
        break;
    case k1:
        value = gpio_input_data_bit_read(K1_GPIO_PORT, K1_PIN);
        break;
    case k2:
        value = gpio_input_data_bit_read(K2_GPIO_PORT, K2_PIN);
        break;
    default:
        break;
    }

    return value;
}


/**
* @brief    按键事件回调函数
* @param    按键结构体指针
* @retval   none
*/
static void common_btn_evt_cb(void *arg)
{
    uint16_t event_id;
    flex_button_t *btn = (flex_button_t *)arg;
    
    event_id = flex_button_event_read(btn);
    
    switch (event_id)
    {
    	case FLEX_BTN_PRESS_CLICK:
            switch (btn->id)
            {
            	case 0:
                    BUTTON_SINGLE_Click_Flag = TRUE;
            		break;
            	case 1:
                    K1_SINGLE_Click_Flag = TRUE;
            		break;
            	case 2:
                    K2_SINGLE_Click_Flag = TRUE;
            		break;
            }
    		break;
    	case FLEX_BTN_PRESS_DOUBLE_CLICK:
            switch (btn->id)
            {
            	case 0:
                    BUTTON_DOUBLE_Click_Flag = TRUE;
            		break;
            	case 1:
                    K1_DOUBLE_Click_Flag = TRUE;
            		break;
            	case 2:
                    K2_DOUBLE_Click_Flag = TRUE;
            		break;
            }
    		break;
        case FLEX_BTN_PRESS_SHORT_START:
            switch (btn->id)
            {
            	case 0:
                    BUTTON_SHORT_PRESS_Flag = TRUE;
            		break;
            	case 1:
                    K1_SHORT_PRESS_Flag = TRUE;
            		break;
            	case 2:
                    K2_SHORT_PRESS_Flag = TRUE;
            		break;
            }
    		break;
        case FLEX_BTN_PRESS_LONG_HOLD:
            switch (btn->id)
            {
            	case 0:
                    BUTTON_LONG_PRESS_Flag = TRUE;
            		break;
            	case 1:
                    K1_LONG_PRESS_Flag = TRUE;
            		break;
            	case 2:
                    K2_LONG_PRESS_Flag = TRUE;
            		break;
            }
    		break;
        case FLEX_BTN_PRESS_LONG_HOLD_UP:
            switch (btn->id)
            {
            	case 0:
                    BUTTON_LONG_PRESS_Flag = FALSE;
            		break;
            	case 1:
                    K1_LONG_PRESS_Flag = FALSE;
            		break;
            	case 2:
                    K2_LONG_PRESS_Flag = FALSE;
            		break;
            }
    		break;
    }

}


/**
* @brief  用户按键初始化配置函数
* @param  none
* @retval none
*/
void user_button_init(void)
{
    int i;

    for (i = 0; i < FLEX_BUTTON_MAX; i ++)
    {
        user_button[i].id = i;
        user_button[i].usr_button_read = common_btn_read;
        user_button[i].cb = common_btn_evt_cb;
        user_button[i].pressed_logic_level = 1;
        user_button[i].short_press_start_tick = FLEX_MS_TO_SCAN_CNT(1000);
        user_button[i].long_press_start_tick = FLEX_MS_TO_SCAN_CNT(1500);
        user_button[i].long_hold_start_tick = FLEX_MS_TO_SCAN_CNT(2000);

        flex_button_register(&user_button[i]);
    }
}

